<template>
  <!-- json编辑器 -->
  <div class="editor-box json-editor">
    <textarea ref="container" :value="value" class="monaco-editor"></textarea>
  </div>
</template>
<script lang="ts">
import { isFunction } from 'lodash'
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
// codemirror 基本样式以及类库
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/blackboard.css'
import * as CodeMirror from 'codemirror'
import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/addon/selection/active-line'
import 'codemirror/mode/javascript/javascript'
// codemirror 折叠
import 'codemirror/addon/fold/foldgutter.css'
import 'codemirror/addon/fold/foldcode'
import 'codemirror/addon/fold/foldgutter'
import 'codemirror/addon/fold/brace-fold'
import 'codemirror/addon/fold/comment-fold'
// lint 相关
import 'codemirror/addon/lint/lint.css'
/* eslint-disable */
// @ts-ignore
require('script-loader!jsonlint')
import 'codemirror/addon/lint/lint'
import 'codemirror/addon/lint/json-lint'

@Component
export default class Editor extends Vue {
  /** 绑定值 */
  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  value!: string

  /** 行数 */
  @Prop({
    type: Number,
    default() {
      return 10
    },
  })
  rows!: number

  /** codeMirror 编辑器实例 */
  public codeMirrorInstance: any

  @Watch('value', { immediate: true })
  getValue(newValue: string) {
    if (this.codeMirrorInstance) {
      const valueEditor = this.codeMirrorInstance.getValue()
      if (newValue !== valueEditor) {
        this.codeMirrorInstance.setValue(newValue)
      }
    }
  }

  /** 编辑器配置 */
  private config: any = {
    tabSize: 4, // tab字符的宽度，默认为4
    styleActiveLine: true, // 当前行背景高亮
    lineNumbers: true, // 显示行数
    line: true,
    mode: 'application/json',
    theme: 'solarized light',
    foldGutter: true,
    lineWrapping: true,
    lint: false,
    gutters: [
      'CodeMirror-linenumbers',
      'CodeMirror-foldgutter',
      'CodeMirror-lint-markers',
    ],
  }

  /** 创建 */
  public mounted(): void {
    this.initEditor()
  }

  /** 销毁editor实例 */
  public destroyEditor(): void {
    if (
      this.codeMirrorInstance &&
      isFunction(this.codeMirrorInstance.destroy)
    ) {
      this.codeMirrorInstance.destroy()
    }
  }

  /** 初始化editor */
  public initEditor(): void {
    // 初始化实例
    this.codeMirrorInstance = CodeMirror.fromTextArea(
      this.$refs.container as HTMLTextAreaElement,
      this.config
    )
    this.codeMirrorInstance.on('change', () => {
      this.$nextTick(() => {
        const valueEditor = this.codeMirrorInstance.getValue()
        this.codeMirrorInstance.setOption('lint', true)
        this.$emit('input', valueEditor)
        this.$emit('change', valueEditor)
      })
    })

    // 销毁
    this.$once('hook:beforeDestroy', () => {
      this.destroyEditor()
    })
  }
}
</script>
<style lang="less" scoped>
.editor-box {
  border: 1px solid #ebebeb;
  font-size: 14px;
  line-height: 1.6;
  position: relative;

  .monaco-editor {
    border-radius: 4px;
    font-size: 12px;
    height: 100%;
    line-height: 1.4;
    width: 100%;
  }
}

.json-editor {
  .CodeMirror {
    height: auto;
    min-height: 300px;
  }
}

.CodeMirror-scroll {
  min-height: 300px;
}

.cm-s-rubyblue .cm-string {
  color: #f08047;
}

.addbtn {
  margin-bottom: 15px;
  margin-left: 30px;
}
</style>
